package com.songhuan.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.songhuan.web.SysConst;
import com.songhuan.web.dto.*;
import com.songhuan.web.dto.query.*;
import com.songhuan.web.entity.*;
import com.songhuan.web.mapper.*;
import com.songhuan.web.service.*;
import com.songhuan.web.tools.Extension;
import com.songhuan.web.tools.JWTUtils;
import com.songhuan.web.tools.dto.PagedResult;
import com.songhuan.web.tools.exception.CustomException;
import com.songhuan.web.dto.AppUserDto;
import com.songhuan.web.dto.OrganizationDto;
import com.songhuan.web.dto.query.AppUserPagedInput;
import com.songhuan.web.entity.AppUser;
import com.songhuan.web.entity.Organization;
import com.songhuan.web.entity.UserFace;
import com.songhuan.web.mapper.AppUserMapper;
import com.songhuan.web.mapper.OrganizationMapper;
import com.songhuan.web.mapper.UserFaceMapper;
import com.songhuan.web.service.AppUserService;
import lombok.SneakyThrows;
import org.apache.commons.beanutils.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 用户功能实现类
 */
@Service
public class AppUserServiceImpl extends ServiceImpl<AppUserMapper, AppUser> implements AppUserService {


    /**
     * 操作数据库的用户表mapper对象
     */
    @Autowired
    private AppUserMapper _AppUserMpper;
    /**
     * 操作数据库的Organization表mapper对象
     */
    @Autowired
    private OrganizationMapper _OrganizationMpper;

    /**
     * 操作数据库的UserFace表mapper对象
     */
    @Autowired
    private UserFaceMapper _UserFaceMpper;


    /**
     * 用户分页查询
     */
    @SneakyThrows
    @Override
    public PagedResult<AppUserDto> List(AppUserPagedInput input) {


        //声明一个支持用户查询的(拉姆达)表达式
        LambdaQueryWrapper<AppUser> queryWrapper = Wrappers.<AppUser>lambdaQuery()
                .eq(input.getId() != null, AppUser::getId, input.getId())
                .eq(input.getCreatorId() != null, AppUser::getCreatorId, input.getCreatorId());

        //如果前端搜索传入Name不为空,则进行精确查询
        if (Extension.isNotNullOrEmpty(input.getName())) {
            queryWrapper = queryWrapper.eq(AppUser::getName, input.getName());
        }

        //如果前端搜索传入Email不为空,则进行精确查询
        if (Extension.isNotNullOrEmpty(input.getEmail())) {
            queryWrapper = queryWrapper.eq(AppUser::getEmail, input.getEmail());
        }

        //如果前端搜索传入getPhoneNumber不为空,则进行精确查询
        if (Extension.isNotNullOrEmpty(input.getPhoneNumber())) {
            queryWrapper = queryWrapper.eq(AppUser::getPhoneNumber, input.getPhoneNumber());
        }

        //如果前端搜索传入getRoleType不为空,则进行精确查询
        if (input.getRoleType() != null) {
            queryWrapper = queryWrapper.eq(AppUser::getRoleType, input.getRoleType());
        }


        //如果前端传入了BirthRange时间范围,则进行时间范围搜索
        if (input.getBirthRange() != null && input.getBirthRange().stream().count() > 1) {
            queryWrapper = queryWrapper.lt(AppUser::getBirth, input.getBirthRange().get(1));
            queryWrapper = queryWrapper.gt(AppUser::getBirth, input.getBirthRange().get(0));
        }


        //按创建时间从大到小排序 最新的显示在最前面
        queryWrapper = queryWrapper.orderByDesc(AppUser::getCreationTime);
        //构建一个分页查询的model
        Page<AppUser> page = new Page<>(input.getPage(), input.getLimit());

        //从数据库进行分页查询获取用户数据
        IPage<AppUser> pageRecords = _AppUserMpper.selectPage(page, queryWrapper);

        //获取所有满足条件的数据行数
        Long totalCount = _AppUserMpper.selectCount(queryWrapper);

        //把用户实体转换成用户传输模型
        List<AppUserDto> items = Extension.copyBeanList(pageRecords.getRecords(), AppUserDto.class);

        for (AppUserDto item : items) {
            //查询用户的人脸数量
            Long count = _UserFaceMpper.selectCount(Wrappers.<UserFace>lambdaQuery().eq(UserFace::getUserId, item.getId()));
            if (count >= 2) {
                item.setFaceAuth(true);
            } else {
                item.setFaceAuth(false);
            }
            //查询用户的班级
            OrganizationDto organizationDto = new OrganizationDto();
            Organization organizationEntity = _OrganizationMpper.selectOne(Wrappers.<Organization>lambdaQuery().eq(Organization::getId, item.getOrganizationId()));
            if (organizationEntity != null) {
                BeanUtils.copyProperties(organizationDto, organizationEntity);
                item.setOrganizationDto(organizationDto);
            }
        }

        //返回一个分页结构给前端
        return PagedResult.GetInstance(items, totalCount);

    }

    public PagedResult<AppUserDto> unRelativeUsers(AppUserPagedInput input) {

        //构建一个分页查询的model
        Page<AppUser> page = new Page<>(input.getPage(), 100);
        //从数据库进行分页查询获取用户数据
        IPage<AppUser> pageRecords = _AppUserMpper.unRelativeUsers(page, input);

        //把用户实体转换成用户传输模型
        List<AppUserDto> items = Extension.copyBeanList(pageRecords.getRecords(), AppUserDto.class);

        //返回一个分页结构给前端
        return PagedResult.GetInstance(items, pageRecords.getTotal());
    }

    /**
     * 用户创建或者修改
     */
    @SneakyThrows
    @Override
    public AppUserDto CreateOrEdit(AppUserDto input) {

        //声明一个用户实体
        AppUser AppUser = new AppUser();

        //把前端传入的input参数拷贝到用户实体
        BeanUtils.copyProperties(AppUser, input);

        //如果前端没有给新密码,则把原始密码继续赋值
        if (Extension.isNotNullOrEmpty(input.getPassword())) {
            input.setPassword(input.getOrginPassword());
        }

        //调用数据库的增加或者修改方法
        saveOrUpdate(AppUser);

        //定义一个返回给前端的用户传输模型
        AppUserDto AppUserDto = new AppUserDto();

        //同理把操作的用户实体拷贝给用户传输模型
        BeanUtils.copyProperties(AppUserDto, AppUser);

        //把传输模型返回给前端
        return AppUserDto;
    }

    /**
     * 单个用户查询
     */
    @SneakyThrows
    @Override
    public AppUserDto Get(AppUserPagedInput input) {
        if (input.getId() == null) {
            return new AppUserDto();
        }
        PagedResult<AppUserDto> pagedResult = List(input);
        return pagedResult.getTotalCount() > 0 ? pagedResult.getItems().stream().findFirst().get() : new AppUserDto();
    }

    @SneakyThrows
    public AppUserDto GetOne(int id) {

        AppUser appUser = _AppUserMpper.selectById(id);

        //定义一个返回给前端的用户传输模型
        AppUserDto appUserDto = new AppUserDto();

        //同理把操作的用户实体拷贝给用户传输模型
        BeanUtils.copyProperties(appUserDto, appUser);

        return appUserDto;
    }


    /**
     * 登录
     */
    public String SignIn(AppUserDto input) {
        LambdaQueryWrapper<AppUser> queryWrapper = Wrappers.<AppUser>lambdaQuery()
                .eq(Extension.isNotNullOrEmpty(input.getUserName()), AppUser::getUserName, input.getUserName())
                .eq(Extension.isNotNullOrEmpty(input.getPassword()), AppUser::getPassword, input.getPassword())
                .eq(Extension.isNotNullOrEmpty(input.getOpenId()), AppUser::getOpenId, input.getOpenId())
                .eq(input.getRoleType() != null, AppUser::getRoleType, input.getRoleType());

        List<AppUser> items = _AppUserMpper.selectList(queryWrapper);
        if (items.stream().count() == 0) {
            //特别注意 登录可以支持openId进行登录,所以如果openId不为空,则说明是微信登录,如果openId为空,则说明是账号密码登录
            if (Extension.isNotNullOrEmpty(input.getOpenId())) {
                throw new CustomException("该用户没有注册,请注册后在尝试");
            } else {
                throw new CustomException("请检查登录的账号或者密码,角色是否都正确!");
            }
        }

        Map<String, String> map = new HashMap<>();
        map.put(SysConst.UserIdClaim, items.get(0).getId().toString());
        map.put(SysConst.RoleTypeClaim, items.get(0).getRoleType().toString());
        //生成token
        String token = JWTUtils.getToken(map);
        return token;
    }

    /**
     * 注册
     */
    @Override
    public AppUserDto Register(AppUserDto input) {


        LambdaQueryWrapper<AppUser> queryWrapper = Wrappers.<AppUser>lambdaQuery()
                .eq(input.getUserName() != null, AppUser::getUserName, input.getUserName())
                .eq(input.getOpenId() != null, AppUser::getOpenId, input.getOpenId())
                .eq(input.getPhoneNumber() != null, AppUser::getPhoneNumber, input.getPhoneNumber());
        //根据用户名称或用户电话号码进行查询
        AppUser appUser = _AppUserMpper.selectOne(queryWrapper);
        if (appUser != null) {
            if (Extension.isNotNullOrEmpty(input.getOpenId())) {
                throw new CustomException("该微信以及绑定了用户了,请直接登录!");
            } else {
                throw new CustomException("该用户名或手机号已经存在!");
            }
        }

        return CreateOrEdit(input);
    }

    @Override
    public List<AppUserCheckStat> GetCheckStat(AppUserDto input) {

        return _AppUserMpper.checkStat(input);
    }
}
